package me.dz.dreamcleaner.listener;

import me.dz.dreamcleaner.DreamCleaner;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static me.dz.dreamcleaner.DreamCleaner.*;
import static me.dz.dreamcleaner.utils.MsgUtils.*;
import static me.dz.dreamcleaner.utils.LogUtils.*;

public class ChatEvent implements Listener {

    private final static HashMap<String,ChatUser> chatMap = new HashMap<>();

    @EventHandler(priority = EventPriority.LOWEST,ignoreCancelled = true)
    public void onChat(PlayerChatEvent e){
        Player player = e.getPlayer();
        String name = e.getPlayer().getName();
        chatMap.putIfAbsent(name,new ChatUser());
        ChatUser user = chatMap.get(name);
        if (oftenEnable){
            if (user.canOftenChat()){
                user.addOften();
            }else {
                stopEvent(e);
                user.resetOftenChat();
                chat(player,lang("chatOften").replace("<time>",user.getOften()));
                if (logEnable && logChat){
                    saveChat(player,e.getMessage(),true);
                }
                return;
            }

        }
        String msg = e.getMessage();
        if (repeatEnable){
            if (!user.canRepeatChat(msg)){
                stopEvent(e);
                chat(player,lang("chatRepeat").replace("<msg>",msg));
                if (logEnable && logChat){
                    saveChat(player,msg,false);
                }
            }
            user.resetRepeatChat(msg);
        }
    }

    @EventHandler(priority = EventPriority.LOWEST,ignoreCancelled = true)
    public void onCmd(PlayerCommandPreprocessEvent e){
        Player player = e.getPlayer();
        String name = e.getPlayer().getName();
        chatMap.putIfAbsent(name,new ChatUser());
        ChatUser user = chatMap.get(name);
        if (cmdEnable){
            if (user.canOftenCmd()){
                user.addCmd();
            }else {
                e.setCancelled(true);
                user.resetOftenCmd();
                chat(player,lang("cmdOften").replace("<time>",user.getCmd()));
            }
        }
    }

    public void stopEvent(PlayerChatEvent event){
        event.setCancelled(true);
        event.getRecipients().clear();
    }

    public static void clear(){
        for (ChatUser user : chatMap.values()){
            user.clearExpired();
        }
    }

    public static class ChatUser {
        private HashMap<String,Long> repeatMap = new HashMap<>();
        private long chatOften = 0;
        private int chatNumber = 0;
        private long cmdOften = 0;
        private int cmdNumber = 0;

        public void clearExpired(){
            HashMap<String,Long> newMap = new HashMap<>();
            Set<Map.Entry<String,Long>> entrySet = repeatMap.entrySet();
            long time = System.currentTimeMillis();
            for (Map.Entry<String,Long> entry : entrySet){
                if (entry.getValue() < time){
                    newMap.put(entry.getKey(),entry.getValue());
                }
            }
            repeatMap = newMap;
        }

        public void resetRepeatChat(String msg){
            repeatMap.put(msg,System.currentTimeMillis() + repeatTime);
        }

        public boolean canRepeatChat(String msg){
            if (repeatMap.containsKey(msg)){
                long now = System.currentTimeMillis();
                long time = repeatMap.get(msg);
                return now >= time;
            }
            return true;
        }

        public void addCmd(){
            cmdNumber++;
        }

        public String getCmd(){
            double time = chatOften - System.currentTimeMillis();
            DecimalFormat df = new DecimalFormat("0.00");
            return df.format(time / 1000);
        }

        public void resetOftenCmd(){
            cmdOften = System.currentTimeMillis() + cmdTime;
            cmdNumber = 0;
        }

        public boolean canOftenCmd(){
            long now = System.currentTimeMillis();
            long time = cmdOften;
            return now >= time && cmdNumber < DreamCleaner.cmdNumber;
        }

        public void addOften(){
            chatNumber++;
        }

        public String getOften(){
            double time = chatOften - System.currentTimeMillis();
            DecimalFormat df = new DecimalFormat("0.00");
            return df.format(time / 1000);
        }

        public void resetOftenChat(){
            chatOften = System.currentTimeMillis() + oftenTime;
            chatNumber = 0;
        }

        public boolean canOftenChat(){
            long now = System.currentTimeMillis();
            long time = chatOften;
            return now >= time && chatNumber < DreamCleaner.oftenNumber;
        }
    }
}
